package org.third.security.cert;

import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;

import sun.security.rsa.RSAPrivateCrtKeyImpl;

public class KeyPairTest {
	public static void main(String[] args) {
		KeyPairTest t = new KeyPairTest();
		t.testKeyPairGenerator();
	}

	private void testKeyPairGenerator() {

		SecureRandom random;
		try {
			KeyPairGenerator keyGen = java.security.KeyPairGenerator.getInstance("RSA");
			random = new SecureRandom();
			keyGen.initialize(4096, random);
			java.security.KeyPair keyPair = keyGen.genKeyPair();
			System.out.println(keyGen);

			java.security.interfaces.RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyPair.getPrivate();
			System.out.println(privateKey.getAlgorithm() + "," + privateKey.getFormat()); //RSA,PKCS#8
			System.out.println(privateKey);

			java.security.interfaces.RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
			System.out.println(publicKey.getAlgorithm() + "," + publicKey.getFormat());//RSA,X.509
			System.out.println(publicKey);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

	}

	/**
	 * detect best JCE by this preference: JSafeJCE &gt; BCFIPS &gt; BC &gt; SunJCE
	 * 
	 * @return provider name
	 */
	public static String detectBestJCE() {
		if (Security.getProvider("JsafeJCE") != null) {
			return "JsafeJCE";
		} else if (Security.getProvider("BCFIPS") != null) {
			return "BCFIPS";
		} else if (Security.getProvider("BC") != null) {
			return "BC";
		} else {
			return "SunJCE";
		}
	}

	/**
	 * detect best secure random
	 * 
	 * @param jceProvider
	 * @return algorithm suitable for provider or empty string if the provider does
	 *         not have one
	 */
	public static String detectBestSecureRandom(String jceProvider) {
		String defaultRandomAlgorithm;
		if (jceProvider.equals("BCFIPS")) {
			defaultRandomAlgorithm = "DEFAULT"; // recommended in https://www.bouncycastle.org/fips/BCUserGuide.pdf
		} else if (jceProvider.equals("BC")) {
			defaultRandomAlgorithm = ""; // BC does not provide any JCE instance as of 1.54
		} else if (jceProvider.equals("JsafeJCE")) {
			defaultRandomAlgorithm = "HMACDRBG128"; // used by CSA FIPS code designed to use JsafeJCE
		} else if (jceProvider.equals("SUN")) {
			defaultRandomAlgorithm = "SHA1PRNG";
		} else {
			defaultRandomAlgorithm = "";
		}
		return defaultRandomAlgorithm;
	}

	/**
	 * get secure random
	 * 
	 * @param randomAlgorithm either randomAlgorithm directly or in format
	 *                        "jce:randomAlgorithm" to override jceProvide argument
	 *                        - may be also "InstanceStrong" to use
	 *                        SecureRandom.getInstanceStrong()
	 * @param jceProvider     may be overriden in randomAlgorithm
	 * @return suitable SecureRandom instance
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchProviderException
	 */
	public static SecureRandom getSecureRandom(String randomAlgorithm, String jceProvider)
			throws NoSuchAlgorithmException, NoSuchProviderException {
		if (randomAlgorithm.contains(":")) {
			String[] split = randomAlgorithm.split(":", 2);
			jceProvider = split[0];
			randomAlgorithm = split[1];
		}
		if (randomAlgorithm.equals("InstanceStrong")) {
			return SecureRandom.getInstanceStrong();
		}
		return randomAlgorithm.isEmpty() ? new SecureRandom() : SecureRandom.getInstance(randomAlgorithm, jceProvider);
	}
}
